package cn.yunyichina.provider.hquery.service.impl;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.common.utils.StringUtils;

import cn.yunyichina.provider.framework.dubbo.service.HisifaceService;
import cn.yunyichina.provider.framework.qiniu.QiniuService;
import cn.yunyichina.provider.hquery.config.Config;
import cn.yunyichina.provider.hquery.constant.FileType;
import cn.yunyichina.provider.hquery.dao.ReportImageDao;
import cn.yunyichina.provider.hquery.entity.ReportImage;
import cn.yunyichina.provider.hquery.thread.PhysicalExamListRunnable;
import cn.yunyichina.provider.hquery.thread.PhysicalReportListRunnable;
import cn.yunyichina.provider.hquery.vo.PhysicalExamVo;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.iface.entity.hisiface.physical.PhysicalExamListVo;
import cn.yunyichina.provider.iface.entity.hisiface.physical.PhysicalExamListVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.physical.PhysicalReportImageVo;
import cn.yunyichina.provider.iface.entity.hisiface.physical.PhysicalReportImageVoResponse;
import cn.yunyichina.utils.convert.JsonUtils;
import net.coobird.thumbnailator.Thumbnails;

/**
 * Created by Administrator on 2017/09/18.
 * 体检报告功能
 */
@Service("physicalExamServiceImpl")
public class PhysicalExamServiceImpl {
	
    private static final Logger logger = LoggerFactory.getLogger(PhysicalExamServiceImpl.class);

    @Autowired
    private ReportImageDao reportImageDao;
    
    //编写Comparator,根据reportTime对ExamineListVoResponse进行排序
    private final Comparator<PhysicalExamListVoResponse> COMPARATOR = new Comparator<PhysicalExamListVoResponse>() {
       public int compare(PhysicalExamListVoResponse o1, PhysicalExamListVoResponse o2) {
           return o1.compareTo(o2);//运用User类的compareTo方法比较两个对象       
       }
    };
    
    /*
	    体检报告列表查询接口
	*/
	public ResponseObject listPhysicalExam(String data ,String sessionId ,String appId) {
		logger.info("体检报告列表 physicalExamList data: "+data);
	    ResponseObject response = new ResponseObject();
	    	
	    PhysicalExamVo requestVo = JsonUtils.parseObject(data, PhysicalExamVo.class);
	    if (StringUtils.isBlank(requestVo.getHospitalCode())
	            ||StringUtils.isBlank(requestVo.getBeginDate())
	            ||StringUtils.isBlank(requestVo.getEndDate())){
	        response.setResultCodeAndMessage("18002","hospitalCode,beginDate,endDate不能为空");
	        return response;
	    }
	    
	    //结果集 体检列表信息
	    List<PhysicalExamListVoResponse> physicalExamListVoResponseList = null;
	    
	    //体检列表查询
	    try {
	    	PhysicalExamListVo physicalExamListVo = new PhysicalExamListVo();
	    	physicalExamListVo.setHospitalCode(requestVo.getHospitalCode());
	    	physicalExamListVo.setPatCardType(requestVo.getPatCardType());
	    	physicalExamListVo.setPatCardNo(requestVo.getPatCardNo());
	    	physicalExamListVo.setBeginDate(requestVo.getBeginDate());
	    	physicalExamListVo.setEndDate(requestVo.getEndDate());
	    	physicalExamListVo.setPatName(requestVo.getPat_name());
	        logger.info("调用调度中心开始");
	        ResCommon<List<PhysicalExamListVoResponse>> physicalExamList  = HisifaceService.getHisifaceClient().getPhysicalExamList(physicalExamListVo);
	        logger.info("调用调度中心结束");
	        if (!"0".equals(physicalExamList.getResultCode())){
	            logger.info("调用调度中心产生异常"+ physicalExamList.getResultMessage());
	            response.setResultCodeAndMessage("18998", physicalExamList.getResultMessage());
	            return response;
	        }
	        logger.info("调用调度中心返回 "+JsonUtils.toJsonString(physicalExamList));
	        
	        physicalExamListVoResponseList = physicalExamList.getResult();
	        
	    } catch (Exception ex) {
	        response.setResultCodeAndMessage("18999","系统异常");
	        return  response;
	    }
	    
	    List<PhysicalExamListVoResponse> emptyReportimeList = new ArrayList<PhysicalExamListVoResponse>();
	    List<PhysicalExamListVoResponse> notEmptyReportimeList = new ArrayList<PhysicalExamListVoResponse>();
	
	    for(PhysicalExamListVoResponse u : physicalExamListVoResponseList){
	        if("".equals(u.getPhyExamTime()) || u.getPhyExamTime() == null){
	            emptyReportimeList.add(u);
	        } else {
	            notEmptyReportimeList.add(u);
	        }
	    }
	    //用我们写好的Comparator对notEmptyReportimeList进行reprotTime日期升序排序
	    Collections.sort(notEmptyReportimeList, COMPARATOR);
	    physicalExamListVoResponseList.clear();
	    physicalExamListVoResponseList.addAll(notEmptyReportimeList);
	    physicalExamListVoResponseList.addAll(emptyReportimeList);
	    
	    if(CollectionUtils.isNotEmpty(physicalExamListVoResponseList)){
	    	
			requestVo.setAppId(appId);
	    	//检查列表入库
			logger.info("listPhysicalExam requevo ={}",new Object[]{JsonUtils.toJsonString(requestVo)});
	    	Thread  listInspectThread = new Thread(new PhysicalExamListRunnable(physicalExamListVoResponseList,requestVo));
	    	listInspectThread.start();
	    }
	    
	    response.setResultCodeAndMessageAndResult("0","成功",physicalExamListVoResponseList);
	    logger.info("【体检报告列表查询】结束, 返回结果=" + JsonUtils.toJsonString(response));
	    return response;
	}
	
	/*
	    体检报告图片查询
	*/
	public ResponseObject listPhysicalExamImage(String data ,String sessionId ,String appId) {
		logger.info("体检报告图片查询 getPhysicalExamImage data: "+data);
	    ResponseObject response = new ResponseObject();
	    PhysicalExamVo requestVo = JsonUtils.parseObject(data, PhysicalExamVo.class);
	    
	    if (StringUtils.isBlank(requestVo.getHospitalCode())
	            ||StringUtils.isBlank(requestVo.getPhy_exam_id())){
	        response.setResultCodeAndMessage("18002","hospitalCode,phyExamId不能为空");
	        return response;
	    }
	    
	    //结果集 体检报告图片信息
	    List<PhysicalReportImageVoResponse> physicalReportImageVoResponseList = null;
	    //查数据库
	    List<ReportImage> reportImgList = reportImageDao.selectByOrgCodeAndReportId(requestVo.getHospitalCode(), requestVo.getPhy_exam_id());
	    //数据库存在记录则不查调度中心
	    if(reportImgList.size() != 0){
	    	physicalReportImageVoResponseList = new ArrayList<PhysicalReportImageVoResponse>();
	    	for(ReportImage reportImage : reportImgList){
	    		PhysicalReportImageVoResponse physicalReportImageVoResponse = new PhysicalReportImageVoResponse();
	    		physicalReportImageVoResponse.setFileAddress(reportImage.getFileAddress());
	    		physicalReportImageVoResponse.setFileType(reportImage.getFileType());
	    		physicalReportImageVoResponseList.add(physicalReportImageVoResponse);
	    	}
	    } else {
	    	//体检报告图片查询
	        try {
	        	
	        	PhysicalReportImageVo physicalReportImageVo = new PhysicalReportImageVo();
	        	physicalReportImageVo.setHospitalCode(requestVo.getHospitalCode());
	        	physicalReportImageVo.setPatCardType(requestVo.getPatCardType());
	        	physicalReportImageVo.setPatCardNo(requestVo.getPatCardNo());
	        	physicalReportImageVo.setPhyExamId(requestVo.getPhy_exam_id());
	            logger.info("调用调度中心开始");
	            ResCommon<List<PhysicalReportImageVoResponse>> physicalReportImageList  = HisifaceService.getHisifaceClient().getPhysicalReportImage(physicalReportImageVo);
	            logger.info("调用调度中心结束");
	            if (!"0".equals(physicalReportImageList.getResultCode())){
	                logger.info("调用调度中心产生异常"+ physicalReportImageList.getResultMessage());
	                response.setResultCodeAndMessage("18998", physicalReportImageList.getResultMessage());
	                return response;
	            }
	            logger.info("调用调度中心返回 "+JsonUtils.toJsonString(physicalReportImageList.getResultCode() + physicalReportImageList.getResultMessage()));
	            physicalReportImageVoResponseList = physicalReportImageList.getResult();
	            
	            if(CollectionUtils.isNotEmpty(physicalReportImageVoResponseList)){
	            	
	            	byte[] bt = null;
	            	ByteArrayInputStream byteArrayInputStream = null;
	            	ByteArrayOutputStream os = null;
	            	//图片下载链接
	        		String bucketURL = Config.QINIU_REPORT_IMG_DOWNLOAD_URL;
	        		//图片上传到七牛云服务器
	            	for (PhysicalReportImageVoResponse physicalReportImageVoResponse : physicalReportImageVoResponseList) {
	            		if(!"".equals(physicalReportImageVoResponse.getFileContent())){
	            			bt = Base64.decodeBase64(physicalReportImageVoResponse.getFileContent().getBytes());
	                		byteArrayInputStream = new ByteArrayInputStream(bt);
	                		String fileName = requestVo.getHospitalCode() +"_report_3_" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()).replace(" ", "_").replace(":", "_") + "." + physicalReportImageVoResponse.getFileType();
	                		com.qiniu.http.Response res = null;
	        	        	if(physicalReportImageVoResponse.getFileType().equals(FileType.JPG)){
	                			//等比例图片压缩
	        	        		logger.info("压缩开始=========== ");
	        	        		os = new ByteArrayOutputStream();  
	        	    	        Thumbnails.of(byteArrayInputStream).size(1100, 750).toOutputStream(os);
	        	    	        byteArrayInputStream = new ByteArrayInputStream(os.toByteArray());
	        	    	        os.flush();
	        	    	        os.close();
	        	        		logger.info("压缩结束=========== ");
	        	        	}
	        				// 调用put方法上传
	        	        	res = QiniuService.upload(byteArrayInputStream, fileName, Config.QINIU_BUCKET_FOR_REPORTIMG);
	        	        	if(res.isOK() || res.statusCode == 614){
	        	        		physicalReportImageVoResponse.setFileAddress(bucketURL + fileName);
	        	        	}else{
	        	        		//失败再重复上传一次
	        	        		res = QiniuService.upload(byteArrayInputStream, fileName, Config.QINIU_BUCKET_FOR_REPORTIMG);
	        	        		if(res.isOK() || res.statusCode == 614){
	        	        			physicalReportImageVoResponse.setFileAddress(bucketURL + fileName);
	        	        		}else{
	        	        			logger.info("report_img_file_qiniu_upload_fail!");
	        	        		}
	                        }
	        	        	byteArrayInputStream.close();
	            		}
	            	}
	            }
	            
	        } catch (Exception ex) {
	        	logger.error("体检报告图片查询异常：" + ex.toString());
	            response.setResultCodeAndMessage("18999","系统异常");
	            return  response;
	        }
	        
	        if(physicalReportImageVoResponseList != null){
				//体检报告图片入库
				requestVo.setAppId(appId);
				logger.info(" listReportImage requestVo={}",new Object[]{JsonUtils.toJsonString(requestVo)});
				Thread  listReportImageThread = new Thread(new PhysicalReportListRunnable(physicalReportImageVoResponseList,requestVo));
				listReportImageThread.start();
			}
	    }
	    
	    //清空fileContent字段的值，避免数据返回给前端过大
	    List<PhysicalReportImageVoResponse> physicalReportImageVoRespList = new ArrayList<PhysicalReportImageVoResponse>();
	    for (PhysicalReportImageVoResponse physicalReportImageVoResponse : physicalReportImageVoResponseList) {
	    	PhysicalReportImageVoResponse physicalReportImageVoResp = new PhysicalReportImageVoResponse();
	    	physicalReportImageVoResp.setFileAddress(physicalReportImageVoResponse.getFileAddress());
	    	physicalReportImageVoResp.setFileType((physicalReportImageVoResponse.getFileType()));
	    	physicalReportImageVoRespList.add(physicalReportImageVoResp);
	    }
	    
	    response.setResultCodeAndMessageAndResult("0","成功",physicalReportImageVoRespList);
	    logger.info("【体检报告图片查询】结束, 返回结果=" + JsonUtils.toJsonString(response));
		return response;
	}
	
	/**
	 * 等比例压缩算法： 
	 * 算法思想：根据压缩基数和压缩比来压缩原图，生产一张图片效果最接近原图的缩略图
	 * @param srcURL 原图地址
	 * @param deskURL 缩略图地址
	 * @param comBase 压缩基数
	 * @param scale 压缩限制(宽/高)比例  一般用1：
	 * 当scale>=1,缩略图height=comBase,width按原图宽高比例;若scale<1,缩略图width=comBase,height按原图宽高比例
	 * @throws Exception
	 * @author shenbin
	 * @createTime 2014-12-16
	 * @lastModifyTime 2014-12-16
	 */
	public ByteArrayInputStream saveMinPhotoes(InputStream srcURL, String filetype, double comBase,
			double scale) throws Exception {
		
		Image src = ImageIO.read(srcURL);
		int srcHeight = src.getHeight(null);
		int srcWidth = src.getWidth(null);
		int deskHeight = 0;// 缩略图高
		int deskWidth = 0;// 缩略图宽
		double srcScale = (double) srcHeight / srcWidth;
		/**缩略图宽高算法*/
		if ((double) srcHeight > comBase || (double) srcWidth > comBase) {
			if (srcScale >= scale || 1 / srcScale > scale) {
				if (srcScale >= scale) {
					deskHeight = (int) comBase;
					deskWidth = srcWidth * deskHeight / srcHeight;
				} else {
					deskWidth = (int) comBase;
					deskHeight = srcHeight * deskWidth / srcWidth;
				}
			} else {
				if ((double) srcHeight > comBase) {
					deskHeight = (int) comBase;
					deskWidth = srcWidth * deskHeight / srcHeight;
				} else {
					deskWidth = (int) comBase;
					deskHeight = srcHeight * deskWidth / srcWidth;
				}
			}
		} else {
			deskHeight = srcHeight;
			deskWidth = srcWidth;
		}
		BufferedImage tag = new BufferedImage(deskWidth, deskHeight, BufferedImage.TYPE_3BYTE_BGR);
		tag.getGraphics().drawImage(src, 0, 0, deskWidth, deskHeight, null); //绘制缩小后的图
		
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ImageIO.write(tag, filetype, byteArrayOutputStream);
		byte[] b = byteArrayOutputStream.toByteArray();
		ByteArrayInputStream ins = new ByteArrayInputStream(b);
		return ins;
	}
}
